package com.example.controller;
import java.time.LocalDateTime;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.ErrorCode;
import com.example.common.Result;
import com.example.constant.UserConstant;
import com.example.exception.BusinessException;
import com.example.model.dto.UserDeleteRequestDTO;
import com.example.model.dto.UserLoginRequestDTO;
import com.example.model.dto.UserRegisterRequestDTO;
import com.example.model.po.User;
import com.example.model.vo.UserSearchVO;
import com.example.service.IUserService;


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * <p>
 * 用户 前端控制器
 *
 * @author LinHui
 * @since 2024-03-28
 */
@RestController
@Slf4j
@RequestMapping("/user")
@Api("用户登录注册类")
@CrossOrigin(origins = "http://localhost:5173/", allowCredentials = "true")
public class UserController {


    @Resource
    private IUserService userService;

    @Resource
    private RedisTemplate<String, Object> rt;


    /**
     *
     * 用户注册
     *
     * @param userRegisterRequestDTO 接受dto
     * @return 返回用户id
     */
    @ApiOperation(value = "用户注册")
    @PostMapping("/register")
    public Result<Long> userRegister(@RequestBody UserRegisterRequestDTO userRegisterRequestDTO) {

        if (userRegisterRequestDTO == null) {
            return Result.error("传入用户数据为空");
        }

        String userAccount = userRegisterRequestDTO.getUserAccount();
        String userPassword = userRegisterRequestDTO.getUserPassword();
        String checkPassword = userRegisterRequestDTO.getCheckPassword();

        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            return Result.error("账号/密码/校验密码为空");
        }
        long id = userService.userRegister(userAccount, userPassword, checkPassword);


        return Result.success(id);
    }


    /**
     *
     * 用户登录
     *
     * @param userLoginRequestDTO 用户传参
     * @param request http
     * @return 返回脱敏用户信息
     */
    @ApiOperation(value = "用户登录")
    @PostMapping("/login")
    public Result<User> userLogin(@RequestBody UserLoginRequestDTO userLoginRequestDTO, HttpServletRequest request) {
        if (userLoginRequestDTO == null) {

            return Result.error("传入用户数据为空");
        }

        String userAccount = userLoginRequestDTO.getUserAccount();
        String userPassword = userLoginRequestDTO.getUserPassword();


        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            return Result.error("账号/密码为空");
        }
        User user = userService.userLogin(userAccount, userPassword, request);

        return Result.success(user);
    }


    /**
     *
     * 根据用户名查询
     *
     * @param userName
     * @return
     */
    @ApiOperation(value = "用户查询类")
    @GetMapping("/search")
    public Result<List<UserSearchVO>> searchUser(String userName, HttpServletRequest request) {
        //鉴定权限
        if (!isAdmin(request)) {
            return Result.error("权限不足");
        }


        log.info("要查询的用户名： {}", userName);
        return Result.success(userService.lambdaQuery().
                like(userName != null, User::getUsername, userName).
                list().
                stream().
                map(user -> {
                    UserSearchVO userSearchVO = new UserSearchVO();
                    //脱敏
                    BeanUtils.copyProperties(userService.getSafteUser(user), userSearchVO);
                    return userSearchVO;

                }).collect(Collectors.toList()));
    }


    @PostMapping("/delete")
    @ApiOperation(value = "用户删除类")
    public Result<Boolean> deleUser(@RequestBody UserDeleteRequestDTO userDeleteRequestDTO, HttpServletRequest request) {
        log.info("进入信息删除, id{}", userDeleteRequestDTO.getId());
        //if (id == null) {
        //    return false;
        //}
        //鉴定权限
        if (!isAdmin(request)) {
            return Result.error("权限不足，无法删除用户");
        }

        log.info("要删除的id: {}", userDeleteRequestDTO.getId());
        if (userDeleteRequestDTO.getId() <= 0) {
            return Result.error("要删除的用户id小于0，错误");
        }

        log.info("要删除的id: {}", userDeleteRequestDTO.getId());
        boolean remove = userService.lambdaUpdate().
                eq(User::getId, userDeleteRequestDTO.getId()).
                remove();

        return Result.success(remove);

    }


    /**
     *
     * 获取用户登录状态
     *
     * @param request
     * @return
     */
    @GetMapping("/current")
    @ApiOperation(value = "用户状态查看")
    public Result<User> getCurrentUser(HttpServletRequest request) {
        User user = (User)request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);

        if (user == null) {
            return Result.error("session中用户状态为空");
        }

        // todo 这里后来要确认用户状态，如果用户是被封号的，那么是不能登录，没有状态的
        //脱敏
        return Result.success(userService.getSafteUser(userService.lambdaQuery().eq(User::getId, user.getId()).one()));
    }



    /**
     *
     * 退出登录
     *
     * @param request
     * @return
     */
    @PostMapping("/outLogin")
    @ApiOperation(value = "用户退出")
    public Result<Boolean> outLogin(HttpServletRequest request) {
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return Result.success(true);
    }


    /**
     *
     * 通过用户标签查找用户
     *
     * @param tagNameList
     * @return
     */
    @ApiModelProperty(value = "通过标签查找用户")
    @GetMapping("/search/tags")
    public Result<List<User>> searchUserByTags(@RequestParam(required = false) List<String> tagNameList) {
        if (CollectionUtils.isEmpty(tagNameList)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        List<User> users = userService.searchUsersByTags(tagNameList);

        return Result.success(users);
    }


    /**
     *
     * 修改用户信息
     *
     * @param user
     * @param request
     * @return
     */
    @ApiModelProperty(value = "修改用户信息")
    @PostMapping("/update")
    public Result<Integer> updateUser(@RequestBody User user, HttpServletRequest request) {
        //只有用户自己和管理员可以修改
        if  (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }


        Object obj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (obj ==  null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        //修改用户信息，当前登录用户信息
        int updateCount = userService.updateUser(user, (User)obj);
        return Result.success(updateCount);

    }


    @ApiModelProperty(value = "获取所有用户信息")
    @GetMapping ("/recommend")
    public Result<List<User>> recommendUsers(int pageSize, int pageNum, HttpServletRequest req) {
        log.info("分页查询");

        User loginUser = (User)req.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);

        if (loginUser == null) {
            throw  new BusinessException(ErrorCode.NOT_LOGIN);
        }

        String key = String.format("meet:user:recommend:%s", loginUser.getId());

        //查询缓存
        List<User> users = (List<User>)rt.opsForValue().get(key);

        if (users != null) {
            return Result.success(users);
        }

        users = userService.lambdaQuery().page(new Page<>(pageNum, pageSize)).getRecords().stream()
                .map(orgUser -> userService.getSafteUser(orgUser))
                .collect(Collectors.toList());

        try {
            rt.opsForValue().set(key, users, 30000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("rdis seet key err", e);
        }


        return Result.success(users);

    }



    /**
     *
     * 鉴定权限
     *
     * @param request
     * @return
     */
    private boolean isAdmin(HttpServletRequest request) {
        User user = (User)request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);

        // todo 后期需要处理，这里需要抛出异常
        if (user == null || user.getUserRole() != UserConstant.ADMIN_ROLE) {
            log.info("权限不够，仅仅管理员可操作");
            return false;
        }

        //参数1：要执行的任务        参数二：是否要传入自定义的线程池
        CompletableFuture<Void> async = CompletableFuture.runAsync(() -> {
            System.out.println("执行要执行的方法");
            System.out.println(Thread.currentThread().getName() + " " + Thread.currentThread().getId());
        });

        //开始执行任务，这里也可以讲上面的任务数传入List集合，然后将集合传入
        //这里要阻塞一下，因为，不阻塞的话，会执接着执行下面的东西
        CompletableFuture.allOf(async).join();


        return true;



    }



    /**
     * 获取最匹配的用户
     *
     * @param num
     * @param request
     * @return
     */
    @GetMapping("/match")
    public Result<List<User>> matchUsers(long num, HttpServletRequest request) {
        if (num <= 0 || num > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }


        User user = userService.getLoginUser(request);


        return Result.success(userService.matchUsers(num, user));
    }




}
